package com.kl.util;

import org.junit.Test;
import org.springframework.util.DigestUtils;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密很常用，比如数据库中密码等敏感字段需要加密存储
 * 核对密码时先以同样的方式对用户输入的密码进行加密，再与数据库中存储的密码比较
 * MD5加密有很多种实现方式，通常用的有两种
 * <p>
 * 只使用md5加密是不行的，很容易被破解。常见的做法有：
 * 1.先对原串进行一些处理，比如先给它拼接一个字符串常量，再进行md5加密，这样即使对方解密成功，也获取不到原串；
 * 2.使用多种加密算法：比如先用md5加密，再对加密的结果使用其它加密算法进行加密，再比如先使用md5加密，对加密的结果再次使用md5加密
 * 这2种方式方式经常一起使用，即先使用"原串+salt"再进行两次MD5加密
 * <p>
 * MD5是一种单向加密算法，只能加密不能解密
 */
public class MD5Test {

    // 方式一：使用JDK自带MessageDigest
    public static String getMD5UseJDK(String str) {
        byte[] digest;
        try {
            MessageDigest md5 = MessageDigest.getInstance("md5");
            // 获取摘要信息
            digest = md5.digest(str.getBytes(StandardCharsets.UTF_8));
            // 16是表示转换为16进制数
            return new BigInteger(1, digest).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 使用Spring自带的DigestUtils
    // 上面是自己封装，太麻烦，Spring已经给我们封装好了
    public static String getMD5UseSpring(String str) {
        return DigestUtils.md5DigestAsHex(str.getBytes());
    }

    // 方式一的另一种写法，实现的效果是相同的
    public static String code(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] byteDigest = md.digest();
            int i;
            StringBuilder buf = new StringBuilder();
            for (byte b : byteDigest) {
                i = b;
                if (i < 0) i += 256;
                if (i < 16) buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            return buf.toString();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }


    @Test
    public void test() {
        // c454e6db49026f80f112883c6b966c55
        System.out.println(getMD5UseJDK("青龙偃月刀"));
        // c454e6db49026f80f112883c6b966c55
        System.out.println(getMD5UseSpring("青龙偃月刀"));
        // c454e6db49026f80f112883c6b966c55
        System.out.println(code("青龙偃月刀"));
    }
}
